package cn.maihe.elg.operation.centers.hymake.channel;

import cn.maihe.elg.operation.centers.hymake.auth.HyMakeCenterAuthConfig;
import cn.maihe.elg.operation.centers.hymake.channel.service.XMBondDownloadChannelService;
import cn.maihe.elg.operation.centers.hymake.channel.service.XMClaimSettlementResultService;
import cn.maihe.elg.operation.centers.hymake.channel.service.XMPayResultReceiveChannelService;
import cn.maihe.elg.operation.centers.hymake.channel.service.XMPushUnsignedChannelService;
import cn.maihe.elg.operation.centers.hymake.channel.service.XMRevokeChannelService;
import cn.maihe.elg.operation.centers.hymake.config.HyMakeInfoConfig;
import cn.maihe.elg.operation.centers.hymake.dto.channel.vo.xm.XMRevokeReqDTO;
import cn.maihe.elg.operation.centers.hymake.dto.handler.vo.xm.XMBaseRespDTO;
import cn.maihe.elg.operation.centers.supports.model.bo.GuaranteeClaimSettlementResultBo;
import cn.maihe.elg.operation.centers.supports.model.bo.GuaranteeRevokeResultBo;
import cn.maihe.elg.operation.centers.supports.model.bo.NoticeGuaranteeApplyResultBo;
import cn.maihe.elg.operation.centers.supports.model.bo.NoticePayResultBo;
import cn.maihe.elg.operation.centers.supports.model.bo.PushCenterGuaranteeBo;
import cn.maihe.elg.operation.model.dto.InnerBaseResp;
import cn.maihe.elg.operation.model.enums.CenterNoEnum;
import cn.maihe.elg.operation.model.enums.RefundAuditStatus;
import cn.maihe.elg.operation.model.enums.RefundOrderStatus;
import cn.maihe.elg.operation.repository.entity.AcceptOrderInfoDO;
import cn.maihe.elg.operation.repository.entity.RefundOrderAttachmentDO;
import cn.maihe.elg.operation.repository.entity.RefundOrderAttachmentDOCondition;
import cn.maihe.elg.operation.repository.entity.RefundOrderInfoDO;
import cn.maihe.elg.operation.service.order.AcceptOrderInfoService;
import cn.maihe.elg.operation.service.order.RefundOrderAttachmentService;
import cn.maihe.elg.operation.supports.system.ElgResourceService;
import cn.maihe.elg.operation.utils.DateUtil;
import cn.maihe.elg.operation.utils.StringUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import javax.annotation.Resource;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @Description
 * @Author caixh
 * @Date 2022/4/1.
 */
@Service
@Slf4j
public class XMCenterInterfaceServiceImpl extends BaseHyMakeCenterInterfaceService {
    @Autowired
    private XMPushUnsignedChannelService xmPushUnsignedChannelService;

    @Autowired
    private XMRevokeChannelService revokeChannelService;

    @Resource
    private HyMakeInfoConfig hyMakeInfoConfig;

    @Resource
    private AcceptOrderInfoService acceptOrderInfoService;

    @Resource
    private XMClaimSettlementResultService claimSettlementResultService;

    @Resource
    private XMPayResultReceiveChannelService xmPayResultReceiveChannelService;

    @Resource
    private XMBondDownloadChannelService xmBondDownloadChannelService;

    @Resource
    RefundOrderAttachmentService refundOrderAttachmentService;

    @Resource
    private ElgResourceService elgResourceService;

    /**
     * 中心枚举
     *
     * @return
     */
    @Override
    public CenterNoEnum getCenterNoEnum() {
        return CenterNoEnum.XIAMEN;
    }

    @Override
    public InnerBaseResp<NoticeGuaranteeApplyResultBo> noticePayResult(NoticePayResultBo bo) {
        return xmPayResultReceiveChannelService.noticePayResult(bo);
    }


    @Override
    public InnerBaseResp<String> pushGuarantee(PushCenterGuaranteeBo bo) {
        return xmBondDownloadChannelService.bondDownload(bo);
    }


    @Override
    public InnerBaseResp<String> pushGuarantee(Path docxPath, String acceptOrderNo) {
        return xmPushUnsignedChannelService.bondDownload(docxPath, acceptOrderNo);
    }

    /**
     * 保函撤销|退保结果通知
     *
     * @param bo
     * @return
     */
    @Override
    public InnerBaseResp noticeGuaranteeRevokeResult(GuaranteeRevokeResultBo bo) {
        HyMakeCenterAuthConfig authConfig = hyMakeInfoConfig.getAuthConfig(CenterNoEnum.XIAMEN);
        AcceptOrderInfoDO acceptOrderInfo = acceptOrderInfoService.getByAcceptOrderNo(bo.getAcceptOrderNo());
//        BidCustomerDO bidCustomer = bidCustomerService.selectById(applyOrderInfo.getBidCustomerId());
        authConfig.getCenterInfo().getAppId();
        Map<String, Object> reqBodyMap = new HashMap();
        reqBodyMap.put("APPID", authConfig.getCenterInfo().getAppId());
        reqBodyMap.put("APPLY_ID", acceptOrderInfo.getCenterApplyId());

        // 退保状态（1：表示已退保,0退保失败）
        if (bo.getAuditPass()) {
            reqBodyMap.put("AUDIT_STATUS", "1");
        } else {
            reqBodyMap.put("AUDIT_STATUS", "0");
        }
        // todo 不确定是否为当前时间
        reqBodyMap.put("AUDIT_TIME", DateUtil.getCurrentDate(DateUtil.FORMAT_DATETIME));
        reqBodyMap.put("REASON", bo.getAuditRemark());
        reqBodyMap.put("TIMESTAMP", DateUtil.getCurrentDate(DateUtil.FORMAT_DADETIME));


        HyMakeCenterAuthConfig hyMakeCenterAuthConfig = hyMakeInfoConfig.getAuthConfig(CenterNoEnum.XIAMEN);
        String signature = hyMakeCenterAuthConfig.getHyMakeAuthorization().signature(reqBodyMap);


        reqBodyMap.put("SIGNATURE", signature);


        XMRevokeReqDTO reqDTO = JSONObject.parseObject(JSONObject.toJSONString(reqBodyMap), XMRevokeReqDTO.class);

        InnerBaseResp<String> innerBaseResp;
        try {
            XMBaseRespDTO xmBaseRespDTO = revokeChannelService.doRequest(getCenterNoEnum(), reqDTO, reqBodyMap);
            if (xmBaseRespDTO.getSuccess()) {
                innerBaseResp = InnerBaseResp.success(null);
            } else {
                innerBaseResp = InnerBaseResp.error(xmBaseRespDTO.getErrorDesc());
            }

        } catch (Exception e) {
            log.error("保函撤销结果通知 >> [{}] 异常:{}", getCenterNoEnum().getCenterName(), e.getMessage(), e);
            innerBaseResp = InnerBaseResp.error("通知异常:" + e.getMessage());
        }
        return innerBaseResp;
    }


    /**
     * 保函理赔申请结果通知
     *
     * @param bo
     * @return
     */
    @Override
    public InnerBaseResp noticeGuaranteeClaimSettlementResult(GuaranteeClaimSettlementResultBo bo) {
        HyMakeCenterAuthConfig authConfig = hyMakeInfoConfig.getAuthConfig(CenterNoEnum.XIAMEN);
        RefundOrderInfoDO refundOrderInfo = bo.getRefundOrderInfo();

        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();

        Map<String, Object> reqBodyMap = new HashMap();
        reqBodyMap.put("APPID", authConfig.getCenterInfo().getAppId());
        reqBodyMap.put("CLAIM_ID", refundOrderInfo.getRefundOrderNo());


        body.add("APPID", authConfig.getCenterInfo().getAppId());
        body.add("CLAIM_ID", refundOrderInfo.getRefundOrderNo());

        if (refundOrderInfo.getStatus() == RefundOrderStatus.REFUNDED.getStatus()) {
            reqBodyMap.put("STATUS", String.valueOf(RefundAuditStatus.PAID.getStatus()));
            String refundAmount = refundOrderInfo.getPayerAmount();
            String amount = StringUtils.isBlank(refundAmount) ? StringUtil.toYuan(refundOrderInfo.getBidBond())
                    : refundAmount;
            reqBodyMap.put("AMOUNT", amount);
            String transferDate = DateUtil.formateDate(refundOrderInfo.getTransferDate(), DateUtil.FORMAT_DATETIME);
            reqBodyMap.put("PAY_TIME", transferDate);
            reqBodyMap.put("REASON", refundOrderInfo.getRemark());


            body.add("STATUS", String.valueOf(RefundAuditStatus.PAID.getStatus()));
            body.add("AMOUNT", amount);
            body.add("PAY_TIME", transferDate);
            body.add("REASON", refundOrderInfo.getRemark());
        } else if (refundOrderInfo.getStatus() == RefundOrderStatus.NO_PASSED.getStatus()) {
            reqBodyMap.put("STATUS", String.valueOf(RefundAuditStatus.NOT_PASSED.getStatus()));
            reqBodyMap.put("REASON", refundOrderInfo.getRemark());

            body.add("STATUS", String.valueOf(RefundAuditStatus.NOT_PASSED.getStatus()));
            body.add("REASON", refundOrderInfo.getRemark());
        } else if (refundOrderInfo.getStatus() == RefundOrderStatus.REFUSED.getStatus()) {
            reqBodyMap.put("STATUS", String.valueOf(RefundAuditStatus.NO_PAYOUTS.getStatus()));
            reqBodyMap.put("REASON", refundOrderInfo.getRemark());

            body.add("STATUS", String.valueOf(RefundAuditStatus.NO_PAYOUTS.getStatus()));
            body.add("REASON", refundOrderInfo.getRemark());
        } else {
            log.error("理赔异常 acceptOrderNo{} status:{}",refundOrderInfo.getAcceptOrderNo(),refundOrderInfo.getStatus());
            return InnerBaseResp.success(refundOrderInfo.getGuaranteeNo());
        }

        InnerBaseResp<String> innerBaseResp;
        String currentDate = DateUtil.getCurrentDate(DateUtil.FORMAT_DADETIME);
        if(refundOrderInfo.getStatus() == RefundOrderStatus.REFUNDED.getStatus() || refundOrderInfo.getStatus() == RefundOrderStatus.REFUSED.getStatus()){
            RefundOrderAttachmentDO refundOrderAttachmentDO = refundOrderAttachmentService.selectOne(RefundOrderAttachmentDOCondition.builder().andRefundOrderIdEq(refundOrderInfo.getId()).andBusinessTypeEq(2).build());
            log.info("refundOrderAttachmentDO:{}",JSONObject.toJSONString(refundOrderAttachmentDO));
            if(Objects.isNull(refundOrderAttachmentDO)){
                log.error("理赔附件不能为空");
                return InnerBaseResp.error(refundOrderInfo.getGuaranteeNo());
            }
            Path path = elgResourceService.getAbsolutePath(refundOrderAttachmentDO.getFilePath());
            try (FileInputStream fis = new FileInputStream(path.toFile())){
                if (refundOrderInfo.getStatus() == RefundOrderStatus.REFUNDED.getStatus() || refundOrderInfo.getStatus() == RefundOrderStatus.REFUSED.getStatus()) {
                    String fileName = refundOrderAttachmentDO.getFileName();
                    byte[] bytes = Files.readAllBytes(path);
                    String fileMd5 = DigestUtils.md5Hex(bytes);

                    reqBodyMap.put("FILE_NAME",fileName);
                    reqBodyMap.put("FILE_MD5", fileMd5);
                    reqBodyMap.put("TIMESTAMP", currentDate);

                    body.add("FILE_NAME",fileName);
                    body.add("FILE_MD5", fileMd5);
                    body.add("TIMESTAMP", currentDate);

                    HyMakeCenterAuthConfig hyMakeCenterAuthConfig = hyMakeInfoConfig.getAuthConfig(CenterNoEnum.XIAMEN);
                    String signature = hyMakeCenterAuthConfig.getHyMakeAuthorization().signature(reqBodyMap);
                    reqBodyMap.put("SIGNATURE", signature);

                    body.add("SIGNATURE", signature);
                    // 1. 封装文件流
                    InputStreamResource resource = new InputStreamResource(fis) {
                        @Override
                        public String getFilename() {
                            return "FILE";
                        }
                        @Override
                        public long contentLength() throws IOException {
                            return fis.available();
                        }
                    };

                    body.add("FILE",resource);
                }

                XMBaseRespDTO xmBaseRespDTO = claimSettlementResultService.doRequestFormFata(getCenterNoEnum(), body);
                if (xmBaseRespDTO.getSuccess()) {
                    innerBaseResp = InnerBaseResp.success(null);
                } else {
                    innerBaseResp = InnerBaseResp.error(xmBaseRespDTO.getErrorCode());
                }
            } catch (Exception e) {
                log.error("理赔结果通知 不予赔付/已赔付>> [{}] 异常:{}", getCenterNoEnum().getCenterName(), e.getMessage(), e);
                innerBaseResp = InnerBaseResp.error("理赔结果通知异常:" + e.getMessage());
            }
            return innerBaseResp;
        }

        reqBodyMap.put("TIMESTAMP", DateUtil.getCurrentDate(DateUtil.FORMAT_DADETIME));
        body.add("TIMESTAMP", currentDate);

        HyMakeCenterAuthConfig hyMakeCenterAuthConfig = hyMakeInfoConfig.getAuthConfig(CenterNoEnum.XIAMEN);
        String signature = hyMakeCenterAuthConfig.getHyMakeAuthorization().signature(reqBodyMap);
        reqBodyMap.put("SIGNATURE", signature);
        body.add("SIGNATURE", signature);

        try {
            XMBaseRespDTO xmBaseRespDTO = claimSettlementResultService.doRequestFormFata(getCenterNoEnum(), body);
            if (xmBaseRespDTO.getSuccess()) {
                innerBaseResp = InnerBaseResp.success(null);
            } else {
                innerBaseResp = InnerBaseResp.error(xmBaseRespDTO.getErrorCode());
            }

        } catch (Exception e) {
            log.error("理赔结果通知 不通过>> [{}] 异常:{}", getCenterNoEnum().getCenterName(), e.getMessage(), e);
            innerBaseResp = InnerBaseResp.error("通知异常:" + e.getMessage());
        }
        return innerBaseResp;
    }

}
